#pragma once
#include "Exchange.hpp"
#include "Binding.hpp"
#include "Message.hpp"
#include "Queue.hpp"

namespace ouyangmq
{
    class VirtualHost
    {
    public:
        using ptr = std::shared_ptr<VirtualHost>;
        VirtualHost(const std::string &hostname, const std::string &basedir, const std::string &dbfile)
            : _host_name(hostname),
              _emp(std::make_shared<ExchangeManager>(dbfile)),
              _bmp(std::make_shared<BindingManager>(dbfile)),
              _mmp(std::make_shared<MessageManager>(basedir)),
              _mqmp(std::make_shared<MsgQueueManager>(dbfile))
        {
            // 加载历史队列
            std::unordered_map<std::string, MsgQueue::ptr> mqm = _mqmp->AllQueues();
            for (auto &q : mqm)
            {
                _mmp->InitQueueMessage(q.first);
            }
        }

        void clear()
        {
            _emp->clear();
            _bmp->clear();
            _mmp->clear();
            _mqmp->clear();
        }

        // 交换机的声明和删除
        bool declareExchange(const std::string &ename, ExchangeType etype,
                             bool edurable, bool eauto_delete, std::unordered_map<std::string, std::string> &eargs)
        {
            return _emp->DeclareExchange(ename, etype, edurable, eauto_delete, eargs);
        }

        void deleteExchange(const std::string &ename)
        {
            // 删除交换机时候，需要删除相关的绑定信息
            _bmp->RemoveExchangBindings(ename);
            return _emp->DeleteExchange(ename);
        }

        // 消息队列的声明和删除
        bool declareQueue(const std::string &qname, bool qdurable,
                          bool qexclusive, bool qauto_delete, std::unordered_map<std::string, std::string> &qargs)
        {
            // 初始化队列的消息句柄，进行消息的存储管理
            _mmp->InitQueueMessage(qname);
            // 队列的创建
            return _mqmp->DeclareQueue(qname, qdurable, qexclusive, qauto_delete, qargs);
        }

        void deleteQueue(const std::string &qname)
        {
            // 删除队列时候，需要删除队列中消息和其绑定信息
            _mmp->DestoryQueueMessage(qname);
            _bmp->RemoveMsgQueueBindings(qname);
            // 删除消息队列管理句柄中的队列对象
            return _mqmp->DeleteQueue(qname);
        }

        // 绑定和解绑
        bool bind(const std::string &ename, const std::string &qname, const std::string &key)
        {
            // 查看需要绑定的交换机和队列是否存在
            Exchange::ptr ep = _emp->GetOneExchage(ename);
            if(ep.get() == nullptr)
            {
                LogModule::LOG(LogModule::LogLevel::ERROR) << "进行绑定失败, 交换机不存在" << ename;
                return false;
            }
            MsgQueue::ptr mqp = _mqmp->GetOneQueue(qname);
            if(mqp.get() == nullptr)
            {
                LogModule::LOG(LogModule::LogLevel::ERROR) << "进行绑定失败, 消息队列不存在" << qname;
                return false;
            }

            // bind的持久化由交换机和消息队列的持久化决定
            // 交换机和消息队列都是持久化bind才持久化
            bool durable = (ep->durable && mqp->durable);
            return _bmp->DeclareBinding(ename, qname, key, durable);
        }

        void unbind(const std::string &ename, const std::string &qname)
        {
            _bmp->DeleteBinding(ename, qname);
        }

        // 获取指定交换机的全部绑定信息
        MsgQueueBindingMap exchangeBindings(const std::string &ename)
        {
            return _bmp->GetExchangeBindings(ename);
        }

        // 推送消息
        bool basicPublish(const std::string &qname, const BasicProperties *bp, const std::string &body)
        {
            // 查看推送消息对应的消息队列是否存在
            MsgQueue::ptr mqp = _mqmp->GetOneQueue(qname);
            if(mqp.get() == nullptr)
            {
                LogModule::LOG(LogModule::LogLevel::ERROR) << "进行发布消息失败, 指定消息队列不存在" << qname;
                return false;
            }
            return _mmp->InsertMessage(qname, bp, body, mqp->durable);
        }

        // 获取指定队列的消息
        MessagePtr basicConsume(const std::string &qname)
        {
            return _mmp->Front(qname);
        }

        // 确认消息
        bool basicAck(const std::string &qname, const std::string &msgid)
        {
            return _mmp->Ack(qname, msgid);
        }

        // 查看指定交换机是否存在
        bool existsExchange(const std::string &ename) {
                return _emp->Exists(ename);
            }

        // 查看指定消息队列是否存在
        bool existsQueue(const std::string &qname) {
                return _mqmp->Exists(qname);
            }
        
        // 查看指定绑定关系是否存在
        bool existsBinding(const std::string &ename, const std::string &qname)
        {
            return _bmp->Exists(ename, qname);
        }
        
    private:
        std::string _host_name;     // 虚拟机标识
        ExchangeManager::ptr _emp;  // 交换机操作句柄
        BindingManager::ptr _bmp;   // 绑定操作句柄
        MessageManager::ptr _mmp;   // 消息操作句柄
        MsgQueueManager::ptr _mqmp; // 消息队列操作句柄
    };
}